package com.qiaofang.applet.service.property.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.mongodb.client.result.UpdateResult;
import com.qiaofang.applet.common.base.MongoBaseService;
import com.qiaofang.applet.common.context.QfContext;
import com.qiaofang.applet.common.context.QfContextHolder;
import com.qiaofang.applet.common.util.RedisKeyUtil;
import com.qiaofang.applet.common.util.RedisUtil;
import com.qiaofang.applet.constants.FirstEstateSaleStautsConstant;
import com.qiaofang.applet.constants.UpDownFlagConstants;
import com.qiaofang.applet.service.member.domain.MemberSubscribe;
import com.qiaofang.applet.service.member.service.EmployeeService;
import com.qiaofang.applet.service.other.domain.CityCompany;
import com.qiaofang.applet.service.other.domain.FirsthandRules;
import com.qiaofang.applet.service.other.domain.PropertyWaterMark;
import com.qiaofang.applet.service.other.domain.ProvinceCity;
import com.qiaofang.applet.service.other.repository.CityCompanyRepository;
import com.qiaofang.applet.service.other.util.DateTypeUtil;
import com.qiaofang.applet.service.property.domain.EstateHouseType;
import com.qiaofang.applet.service.property.domain.EstateImage;
import com.qiaofang.applet.service.property.domain.FirsthandEstate;
import com.qiaofang.applet.service.property.repository.FirsthandEstateRepository;
import com.qiaofang.applet.service.property.service.CommonService;
import com.qiaofang.applet.service.property.service.FirsthandEstateService;
import com.qiaofang.applet.service.property.service.QueryCommonService;
import com.qiaofang.applet.service.property.service.dto.*;
import com.qiaofang.applet.service.property.service.mapstruct.FirsthandEstateMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FirsthandEstateServiceImpl extends MongoBaseService<FirsthandEstate, String> implements FirsthandEstateService, QueryCommonService {

    private final FirsthandEstateRepository firsthandEstateRepository;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private FirsthandEstateMapper firsthandEstateMapper;

    @Autowired
    private EmployeeService employeeService;
    
    @Autowired
    private CommonService commonService;

    @Autowired
    private CityCompanyRepository cityCompanyRepository;

    @Autowired
    private RedisUtil redisUtil;
    

    @Autowired
    public FirsthandEstateServiceImpl(FirsthandEstateRepository repository) {
        super(repository);
        this.firsthandEstateRepository = repository;
    }

    @Override
    public FirsthandEstate findByEstateUuidAndCityCode(String estateUuid, String cityCode) {
        FirsthandEstate firsthandEstate = firsthandEstateRepository.findByEstateUuidAndCorporationCodeAndCityCode(estateUuid, QfContextHolder.getContext().getCorporationCode(), cityCode);

        return firsthandEstate;
    }

    @Override
    public FirsthandEstate findByEstateUniqueUuid(String estateUniqueUuid) {
        FirsthandEstate firsthandEstate = firsthandEstateRepository.findFirstByEstateUniqueUuid(estateUniqueUuid);
        //新房水印处理
        if (firsthandEstate != null && !CollectionUtils.isEmpty(firsthandEstate.getImageList())) {
            List<EstateImage> estateImageList = new ArrayList<>();

            String propertyWaterMarkKey = RedisKeyUtil.getPropertyWaterMarkKey(firsthandEstate.getCompanyUuid());
            Object obj = redisUtil.hget(propertyWaterMarkKey, estateUniqueUuid);
            if (obj != null) {
                estateImageList = JSONObject.parseArray(JSONObject.toJSONString(obj), EstateImage.class);
            } else {
                PropertyWaterMark propertyWaterMark = getPropertyWaterMark();
                for (EstateImage estateImage : firsthandEstate.getImageList()) {
                    estateImage.setImageUrl(commonService.propertyWaterMark(estateImage.getImageUrl(), propertyWaterMark));
                    estateImageList.add(estateImage);
                }
                redisUtil.hset(propertyWaterMarkKey, estateUniqueUuid, estateImageList);
            }
            firsthandEstate.setImageList(estateImageList);
        }
        //新房下户型图水印处理
        if (firsthandEstate != null && !CollectionUtils.isEmpty(firsthandEstate.getHouseTypeList())){

            List<EstateHouseType> estateHouseTypeList = new ArrayList<>();;
            String propertyWaterMarkKey = RedisKeyUtil.getPropertyWaterMarkKey(firsthandEstate.getCompanyUuid());
            Object obj = redisUtil.hget(propertyWaterMarkKey, estateUniqueUuid + "houseType");
            if (obj != null) {
                estateHouseTypeList = JSONObject.parseArray(JSONObject.toJSONString(obj), EstateHouseType.class);
            } else {
                PropertyWaterMark propertyWaterMark = getPropertyWaterMark();
                for (EstateHouseType estateHouseType : firsthandEstate.getHouseTypeList()) {
                    estateHouseType.setImageUrl(commonService.propertyWaterMark(estateHouseType.getImageUrl(), propertyWaterMark));
                    estateHouseTypeList.add(estateHouseType);
                }
                redisUtil.hset(propertyWaterMarkKey, estateUniqueUuid + "houseType", estateHouseTypeList);
            }
            firsthandEstate.setHouseTypeList(estateHouseTypeList);
        }

        return firsthandEstate;
    }

    private Query createFindQuery(FirsthandEstateQueryDto queryDto) {
        Query query = new Query();

        QfContext qfContext = QfContextHolder.getContext();

        Criteria criteria = Criteria.where("corporationCode").is(StringUtils.defaultString(queryDto.getCorporationCode(), qfContext.getCorporationCode()));

        if (StringUtils.isNotBlank(queryDto.getCityCode())) {
            criteria.and("city").is(queryDto.getCityCode());
        } else if (!CollectionUtils.isEmpty(queryDto.getCityCodes())){
            criteria.and("city").in(queryDto.getCityCodes());
        }
        if (StringUtils.isNotBlank(queryDto.getAreaCode())) {
            criteria.and("area").is(queryDto.getAreaCode());
        }
        if (StringUtils.isNotBlank(queryDto.getEstateName())) {
            criteria.and("estateName").regex(".*?" + queryDto.getEstateName() + ".*");
        }
        if (StringUtils.isNotBlank(queryDto.getUpDownFlag())) {
            criteria.and("upDownFlag").is(queryDto.getUpDownFlag());
        }
        if (queryDto.getMinBuildingArea() != null && queryDto.getMaxBuildingArea() != null) {
            criteria.andOperator(
                    Criteria.where("minBuildingArea").gte(queryDto.getMinBuildingArea()),
                    Criteria.where("maxBuildingArea").lte(queryDto.getMaxBuildingArea())
            );
        } else if (queryDto.getMinBuildingArea() != null) {
            criteria.andOperator(
                    Criteria.where("minBuildingArea").gte(queryDto.getMinBuildingArea()),
                    Criteria.where("maxBuildingArea").lte(new BigDecimal(999999999))
            );
        } else if (queryDto.getMaxBuildingArea() != null) {
            criteria.andOperator(
                    Criteria.where("minBuildingArea").gte(new BigDecimal(0)),
                    Criteria.where("maxBuildingArea").lte(queryDto.getMaxBuildingArea())
            );
        }
        if (!CollectionUtils.isEmpty(queryDto.getPropertyType())) {
            criteria.and("propertyType").regex(".*?" + queryDto.getPropertyType().get(0) + ".");
        }
        if (!CollectionUtils.isEmpty(queryDto.getHouseType())) {
            criteria.and("houseTypeList.bedroom").in(queryDto.getHouseType());
        }
        if (queryDto.getRecommend() != null) {
            criteria.and("recommend").is(queryDto.getRecommend());
        }
        if (!CollectionUtils.isEmpty(queryDto.getEstateUniqueUuids())) {
            criteria.and("estateUniqueUuid").in(queryDto.getEstateUniqueUuids());
        }
        if (!CollectionUtils.isEmpty(queryDto.getNotEstateUniqueUuids())) {
            criteria.and("estateUniqueUuid").nin(queryDto.getNotEstateUniqueUuids());
        }

        //criteria.and("saleStatus").ne("");

        if (queryDto.getNewStatus() != null && queryDto.getNewStatus()){
            criteria.and("createdTime").gte(new Timestamp(System.currentTimeMillis() - (7 * DateUtil.DAY_MILLISECONDS)));
        }

        //新增开盘时间
        if (ObjectUtil.isNotNull(queryDto.getOpenDate())){
            Date date = new Date();
            switch (queryDto.getOpenDate()) {
                case 1:
                    criteria.and("openDate").lte(DateTypeUtil.getBeginOrAfterDay(date, Calendar.MONTH, 1)).gte(date);
                    break;
                case 3:
                    criteria.and("openDate").lte(DateTypeUtil.getBeginOrAfterDay(date, Calendar.MONTH, 3)).gte(date);
                    break;
                case 6:
                    criteria.and("openDate").lte(DateTypeUtil.getBeginOrAfterDay(date, Calendar.MONTH, 6)).gte(date);
                    break;
                case -1:
                    criteria.and("openDate").gte(DateTypeUtil.getBeginOrAfterDay(date, Calendar.MONTH, -1)).lte(date);
                    break;
                case -3:
                    criteria.and("openDate").gte(DateTypeUtil.getBeginOrAfterDay(date, Calendar.MONTH, -3)).lte(date);
                    break;
                case -6:
                    criteria.and("openDate").gte(DateTypeUtil.getBeginOrAfterDay(date, Calendar.MONTH, -6)).lte(date);
                    break;
            }
        }

        if (queryDto.getMinTotalPrice() != null && queryDto.getMaxTotalPrice() != null) {
            Criteria criteria1 = new Criteria().andOperator(Criteria.where("minTotalPrice").lte(queryDto.getMinTotalPrice())
                    , Criteria.where("maxTotalPrice").gte(queryDto.getMinTotalPrice()));
            Criteria criteria2 = new Criteria().andOperator(Criteria.where("minTotalPrice").lte(queryDto.getMaxTotalPrice())
                    , Criteria.where("maxTotalPrice").gte(queryDto.getMaxTotalPrice()));
            Criteria criteria3 = new Criteria().andOperator(Criteria.where("minTotalPrice").gt(queryDto.getMinTotalPrice())
                    , Criteria.where("maxTotalPrice").lt(queryDto.getMaxTotalPrice()));
            criteria.orOperator(criteria1, criteria2, criteria3);
        } else if (queryDto.getMinTotalPrice() != null) {
            criteria.and("maxTotalPrice").gte(queryDto.getMinTotalPrice());
        } else if (queryDto.getMaxTotalPrice() != null) {
            criteria.and("minTotalPrice").lte(queryDto.getMaxTotalPrice());
        }

        Criteria criteriaB = new Criteria();
        if (queryDto.getMinAveragePrice() != null && queryDto.getMaxAveragePrice() != null) {
            criteriaB.andOperator(
                    Criteria.where("averagePrice").gte(queryDto.getMinAveragePrice()),
                    Criteria.where("averagePrice").lte(queryDto.getMaxAveragePrice())
            );
        } else if (queryDto.getMinAveragePrice() != null) {
            criteriaB.andOperator(
                    Criteria.where("averagePrice").gte(queryDto.getMinAveragePrice()),
                    Criteria.where("averagePrice").lte(new BigDecimal(999999999))
            );
        } else if (queryDto.getMaxAveragePrice() != null) {
            criteriaB.andOperator(
                    Criteria.where("averagePrice").gte(new BigDecimal(0)),
                    Criteria.where("averagePrice").lte(queryDto.getMaxAveragePrice())
            );
        }else {
            criteriaB.and("averagePrice").ne(null);
        }

        Criteria criteriaC = new Criteria();
        // 待开盘就是待售
        //小程序和pc列表查询未开盘
        if (StringUtils.isNotBlank(queryDto.getWaitOpen()) && queryDto.getWaitOpen().equals("1")) {
            criteriaC.andOperator(
                    Criteria.where("saleStatus").is(FirstEstateSaleStautsConstant.SALE_STATUS_1),
                    Criteria.where("saleStatus").ne("")
            );
            //criteria.and("saleStatus").is(FirstEstateSaleStautsConstant.SALE_STATUS_1);
        } else {
            if (queryDto.getComingOpen() != null && queryDto.getComingOpen()) {
                criteriaC.andOperator(
                        Criteria.where("openDate").gt(new Date()),
                        Criteria.where("openDate").lt(DateTypeUtil.getBeginOrAfterDay(new Date(), Calendar.DAY_OF_MONTH, +30)),
                        Criteria.where("saleStatus").is(queryDto.getSaleStatus()
                        ));
            } else {
                if (StringUtils.isNotBlank(queryDto.getSaleStatus())) {
                    criteriaC.andOperator(
                            Criteria.where("saleStatus").is(queryDto.getSaleStatus()),
                            Criteria.where("saleStatus").ne("")
                    );
                    //criteria.and("saleStatus").is(queryDto.getSaleStatus());
                }
            }
        }

        Criteria criteriaD = new Criteria();

        if (!CollectionUtils.isEmpty(queryDto.getSaleStatusList())) {
            criteriaD.andOperator(
                    Criteria.where("saleStatus").in(queryDto.getSaleStatusList()),
                    Criteria.where("saleStatus").ne("")
            );
            //criteria.and("saleStatus").in(queryDto.getSaleStatusList());
        }
        query.addCriteria(new Criteria().andOperator(criteria, criteriaB, criteriaC, criteriaD));

        return query;
    }

    @Override
    public Page<FirsthandEstate> findAllByParams(FirsthandEstateQueryDto queryDto, Pageable pageable) {
        // 1、拼查询公共条件
        Query queryCriteria = createFindQuery(queryDto);

        // 2、拼分页参数
        queryCriteria.with(pageable);

        // 3、拼排序参数
        createFindSort(queryCriteria, queryDto.getSort());

        // 4、查询记录条件
        long count = mongoTemplate.count(queryCriteria, FirsthandEstate.class);
        List<FirsthandEstate> firsthandEstates = new ArrayList<>();
        if (count > 0) {
            // 6、分页查询数据
            List<FirsthandEstate> content = mongoTemplate.find(queryCriteria, FirsthandEstate.class);
            firsthandEstates = cityCodeToCityName(content);
        }
        return PageableExecutionUtils.getPage(firsthandEstates, pageable, () -> count);
    }

    @Override
    public Page<FirsthandEstate> findAllHotFirsthandByParams(FirsthandEstateQueryDto queryDto, Pageable pageable) {

        // 1、拼查询公共条件
        Query queryCriteria = createFindQuery(queryDto);

        // 2、拼分页参数
        queryCriteria.with(pageable);

        // 3、拼排序参数
        queryCriteria.with(Sort.by(Sort.Order.asc("recommendSort")));

        // 4、查询记录条件
        long count = mongoTemplate.count(queryCriteria, FirsthandEstate.class);
        List<FirsthandEstate> firsthandEstates = new ArrayList<>();
        if (count > 0) {
            // 6、分页查询数据
            List<FirsthandEstate> content = mongoTemplate.find(queryCriteria, FirsthandEstate.class);
            firsthandEstates = cityCodeToCityName(content);
        }
        return PageableExecutionUtils.getPage(firsthandEstates, pageable, () -> count);
    }

    /**
     * 城市code to name
     *
     * @param list
     * @return
     */
    public List<FirsthandEstate> cityCodeToCityName(List<FirsthandEstate> list) {

        List<String> cityCodes = list.stream().map(FirsthandEstate::getCity).distinct().collect(Collectors.toList());
        List<String> areaCodes = list.stream().map(FirsthandEstate::getArea).distinct().collect(Collectors.toList());
        Query query = new Query();
        Criteria criteria = Criteria.where("areaCode").in(cityCodes);
        query.addCriteria(criteria);
        List<ProvinceCity> provinceCitiesCity = mongoTemplate.find(query, ProvinceCity.class);
        Query queryArea = new Query();
        Criteria criteriaArea = Criteria.where("areaCode").in(areaCodes);
        queryArea.addCriteria(criteriaArea);
        List<ProvinceCity> provinceCitiesArea = mongoTemplate.find(queryArea, ProvinceCity.class);

        list.forEach(s -> {
            for (ProvinceCity provinceCity : provinceCitiesCity) {
                if (StringUtils.equals(provinceCity.getAreaCode(), s.getCity())) {
                    s.setCityName(provinceCity.getName());
                }
            }
        });
        list.forEach(s -> {
            for (ProvinceCity provinceCity : provinceCitiesArea) {
                if (StringUtils.equals(provinceCity.getAreaCode(), s.getArea())) {
                    s.setAreaName(provinceCity.getName());
                }
            }
        });
        return list;
    }


    @Override
    public List<FirsthandEstate> findAllByParams(FirsthandEstateQueryDto queryDto) {
        // 1、拼查询公共条件
        Query queryCriteria = createFindQuery(queryDto);
        List<FirsthandEstate> firsthandEstateList = mongoTemplate.find(queryCriteria, FirsthandEstate.class);
        ////图片水印处理
        //PropertyWaterMark propertyWaterMark = getPropertyWaterMark();
        //for (FirsthandEstate firsthandEstate : firsthandEstateList) {
        //    firsthandEstate.setImageUrl(commonService.propertyWaterMark(firsthandEstate.getImageUrl(), propertyWaterMark));
        //}
        return firsthandEstateList;
    }

    @Override
    public Page<FirsthandEstate> findAllByUuids(FirsthandEstateQueryDto queryDto, Pageable pageable) {
        // 1、拼查询公共条件
        Query queryCriteria = createFindQuery(queryDto);

        long count = mongoTemplate.count(queryCriteria, FirsthandEstate.class);
        List<FirsthandEstate> result = new ArrayList<>();
        if (count > 0) {
            result = mongoTemplate.find(queryCriteria.with(pageable), FirsthandEstate.class);
        }

        return PageableExecutionUtils.getPage(result, pageable, () -> count);
    }

    @Override
    public List<FirsthandEstate> findAllByParamsAndRand(FirsthandEstateQueryDto queryDto) {
        List<FirsthandEstate> result = new ArrayList<>();
        int pageSize = 4; //默认是4

        // 1、拼查询公共条件
        Query queryCriteria = createFindQuery(queryDto);


        long count = mongoTemplate.count(queryCriteria, FirsthandEstate.class);
        if (count > 0) {
            Double allPage = Math.floor(count / pageSize);
            int pageNo = 0;
            if (allPage > 0) {
                pageNo = new Random().nextInt(allPage.intValue());
            }
            // 2、拼分页参数
            Pageable pageable = PageRequest.of(pageNo, pageSize);
            queryCriteria.with(pageable);
        }
        return result;
    }

    @Override
    public List<FirsthandEstate> findAllByParamsAndRandForEstatePK(FirstEstateGuessLikeForPKDto queryDto, Pageable pageable) {
        Query query = new Query();
        Criteria criteria = new Criteria();
        criteria.and("corporationCode").is(QfContextHolder.getContext().getCorporationCode());
        criteria.and("cityCode").is(queryDto.getCityCode());
        criteria.and("area").is(queryDto.getAreaCode());
        criteria.and("deleted").is(false);
        criteria.and("upDownFlag").is(UpDownFlagConstants.UP_FLAG.getValue());
        query.addCriteria(criteria);
        query.with(Sort.by(Sort.Order.desc("updateTime")));
        query.with(pageable);
        //PropertyWaterMark propertyWaterMark = getPropertyWaterMark();
        //List<FirsthandEstate> firsthandEstateList =
        //        Optional.ofNullable(mongoTemplate.find(query, FirsthandEstate.class)).orElseGet(Lists::newArrayList)
        //                .stream().map(firsthandEstate -> {
        //            firsthandEstate.setImageUrl(commonService.propertyWaterMark(firsthandEstate.getImageUrl(), propertyWaterMark));
        //            return firsthandEstate;
        //        }).collect(Collectors.toList());
        return Optional.ofNullable(mongoTemplate.find(query, FirsthandEstate.class)).orElseGet(Lists::newArrayList);
    }

    @Override
    public void updateFirsthandEstate(FirsthandEstate firsthandEstate) {
        updateById(firsthandEstate);
    }

    @Override
    public long batchDownFirsthand(FirsthandRules firsthandRules, String corporationCode, long currentTimeMillis) {
        if (!firsthandRules.isValidParam()){
            return 0;
        }
        Criteria criteria = createCriteria(currentTimeMillis);
        criteria.and("corporationCode").is(corporationCode);

        Criteria criteria1 = new Criteria();
        List<Criteria> list = new LinkedList<>();
        if (firsthandRules.isHousePhoto() && firsthandRules.getHousePhotoNum() != null && firsthandRules.getHousePhotoNum() >= 0){
            list.add(Criteria.where ("imageList." + firsthandRules.getHousePhotoNum()).exists(false));
        }
        if (firsthandRules.isHouseTypePhoto()){
            list.add(Criteria.where("houseTypeList.0").exists(false));
        }
        if (list.size() > 1) {
            criteria1.orOperator(list.toArray(new Criteria[list.size()]));
        }else {
            criteria1 = list.get(0);
        }

        Query query = new Query();
        query.addCriteria(new Criteria().andOperator(criteria, criteria1));
        Update update = new Update();
        update.set("upDownFlag", UpDownFlagConstants.DOWN_FLAG.getValue());
        update.set("rulesHandle", true);
        UpdateResult updateResult = mongoTemplate.updateMulti(query, update, FirsthandEstate.class);
        return updateResult.getModifiedCount();
    }

    @Override
    public List<String> getUndisposedUuidList(String companyUuid, long currentTimeMillis) {
        Criteria criteria = createCriteria(currentTimeMillis);
        criteria.and("companyUuid").is(companyUuid);
        TypedAggregation<FirsthandEstate> tagg = TypedAggregation.newAggregation(FirsthandEstate.class, Arrays.asList(
                TypedAggregation.match(criteria),
                TypedAggregation.group("estateUuid").first("estateUuid").as("estateUuid"),
                TypedAggregation.project("estateUuid")
        ));
        AggregationResults result = mongoTemplate.aggregate(tagg, FirsthandEstate.class);
        List<FirsthandEstate> resultList = result.getMappedResults();
        List<String> uuidList = Optional.ofNullable(resultList).orElseGet(Lists::newArrayList).stream().map(FirsthandEstate::getEstateUuid).collect(Collectors.toList());
        return uuidList;
    }

    @Override
    public long batchProcessingByUuidList(List<String> uuidList, String companyUuid, String upDownFlag) {
        if (CollectionUtils.isEmpty(uuidList)){
            return 0;
        }
        Criteria criteria = new Criteria();
        criteria.and("companyUuid").is(companyUuid);
        criteria.and("estateUuid").in(uuidList);
        Update update = new Update();
        update.set("upDownFlag", upDownFlag);
        update.set("rulesHandle", true);
        UpdateResult updateResult = mongoTemplate.updateMulti(new Query().addCriteria(criteria), update, FirsthandEstate.class);
        return updateResult.getModifiedCount();
    }

    @Override
    public Page<FirstEstateSubscribeDto> domainToPageDto(Page<FirsthandEstate> firsthandEstatePage, List<MemberSubscribe> subscribeList) {
        List<FirstEstateSubscribeDto> result = new ArrayList<>();

        if (firsthandEstatePage.getTotalElements() > 0) {
            result = firsthandEstatePage.getContent().stream().map(firsthandEstateMapper::domainToSubscribeListDto).collect(Collectors.toList());

            for (FirstEstateSubscribeDto estateListDto : result) {
                for (MemberSubscribe memberSubscribe : subscribeList) {
                    if (StringUtils.equals(estateListDto.getEstateUniqueUuid(),memberSubscribe.getEstateUniqueUuid())){
                        estateListDto.setSubscribeTime(memberSubscribe.getSubscribeTime());
                    }
                }
            }
            result = result.stream().sorted(Comparator.comparing(FirstEstateSubscribeDto::getSubscribeTime).reversed()).collect(Collectors.toList());
        }
        return PageableExecutionUtils.getPage(result, firsthandEstatePage.getPageable(), () -> firsthandEstatePage.getTotalElements());
    }

    private Criteria createCriteria(long currentTimeMillis) {
        Criteria criteria = new Criteria();
        criteria.and("rulesHandle").is(false);
        criteria.and("updateTime").lte(new Timestamp(currentTimeMillis));
        //匹配没有手动上架 或 手动上架时间在7天前
        criteria.orOperator(Criteria.where("manualUpTime").exists(false), Criteria.where("manualUpTime").is(null), Criteria.where("manualUpTime").lt(new Timestamp(currentTimeMillis - (7 * DateUtil.DAY_MILLISECONDS))));
        return criteria;
    }

    @Override
    public List<FirsthandEstateComparedDetailDto> comparedEstateData(ComparedEstateDto comparedEstateDto) {
        log.info("对比楼盘数据入参:{}", JSONObject.toJSONString(comparedEstateDto));
        //查询对比的楼盘
        Query query = new Query();
        query.addCriteria(Criteria.where("corporationCode").is(QfContextHolder.getContext().getCorporationCode()));
        query.addCriteria(Criteria.where("city").is(comparedEstateDto.getCityCode()));
        query.addCriteria(Criteria.where("estateUniqueUuid").in(comparedEstateDto.getEstateUniqueUuidList()));
        List<FirsthandEstate> firsthandEstateList = mongoTemplate.find(query, FirsthandEstate.class);
        long start = System.currentTimeMillis();

        List<FirsthandEstateComparedDetailDto> firsthandEstateComparedDetailDtos = firsthandEstateMapper.domainListToList(firsthandEstateList);

        PropertyWaterMark propertyWaterMark = getPropertyWaterMark();
        for (FirsthandEstateComparedDetailDto firsthandEstateComparedDetailDto : firsthandEstateComparedDetailDtos) {
            firsthandEstateComparedDetailDto.setImgUrl(commonService.propertyWaterMark(firsthandEstateComparedDetailDto.getImgUrl(), propertyWaterMark));
        }
        if (CollectionUtils.isEmpty(firsthandEstateComparedDetailDtos)){
            return new ArrayList<>();
        }
        log.info("组装了:{}次新房对比数据经纪人固定展示位手机号,耗时:{}ms", firsthandEstateComparedDetailDtos.size(), System.currentTimeMillis() - start);
        return firsthandEstateComparedDetailDtos;
    }

    @Override
    public String getFirstEstateEmployeePhone(String uniqueUuid) {
        PropertyEmpDto propertyEmpDto = employeeService.getEmployeeDtoByFirsthand(uniqueUuid);
        return propertyEmpDto == null ? null : propertyEmpDto.getEmployeeListDto().getMobilePhone();
    }

    @Override
    public List<EstateHouseTypeDetailDto> dealEstateHouseTypeWaterMark(List<EstateHouseTypeDetailDto> list) {
        ArrayList<EstateHouseTypeDetailDto> estateHouseTypeDetailDtos = new ArrayList<>();
        PropertyWaterMark propertyWaterMark = getPropertyWaterMark();
        for (EstateHouseTypeDetailDto detailDto : list) {
            detailDto.setImageUrl(commonService.propertyWaterMark(detailDto.getImageUrl(), propertyWaterMark));
            estateHouseTypeDetailDtos.add(detailDto);
        }
        return estateHouseTypeDetailDtos;
    }

    /**
     * 获取公司水印设置
     * @return
     */
    private PropertyWaterMark getPropertyWaterMark() {
        QfContext context = QfContextHolder.getContext();
        List<CityCompany> cityCompanyList = cityCompanyRepository.findAllByCorporationCodeAndCityCodeAndMainCityFlag(context.getCorporationCode(), context.getCityCode(), 1);
        if (CollectionUtils.isEmpty(cityCompanyList)) {
            return null;
        }
        return cityCompanyList.get(0).getPropertyWaterMark();
    }
}
